
open Common

module type T =
sig

  module Key : Eqtype.T

  type 'a cache

  val lookup : 'a cache -> Key.t -> 'a option
  val cache : 'a cache -> Key.t -> 'a -> unit
  val clear : 'a cache -> unit
  val remove : 'a cache -> Key.t -> unit
  val save : 'a cache -> string -> unit
  val load : string -> 'a cache
    
end


module S(Key : Eqtype.T) : T with module Key = Key =
struct 

  module Key = Key
  module H = Hashtbl'
  module M = Marshal

  type 'a cache = (Key.t,'a) H.t

  let lookup cache key = try Some(H.find cache key) with Not_found -> None

  let cache c k v = 
    try
      ignore (H.find c k);
      failwith "cache: cashe already contains binding"
    with Not_found -> H.add c k v

  let clear c = H.clear c

  let rec remove c k = 
    begin 
      if H.mem c k then (H.remove c k; remove c k)
      else ()
    end

  let save c file = 
    let out = open_out file in
    begin
      M.to_channel out c [];
      close_out out
    end

  let default_size = 100

  let load file =
    if not (Sys.file_exists file) then H.create default_size else
    let inf = open_in file in
    let cache = (M.from_channel inf : 'a cache) in
      begin 
        close_in inf;
        cache
      end 

end


  
